package com.xtm.exercise.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * DateUtil工具类API速查表:
 * 1.按指定样式获得系统时间,样式参数如yyyy-MM-dd,yyyy-MM-dd HH:mm:ss等  formatCurTime(String pattern)
 * 2.根据时区和指定样式获取该时区下的系统时间 formatCurTime(String timeZone, String pattern)
 * 3.根据语言环境获得系统日期  getCurTime(Locale locale)
 * 4.根据给定的字符串日期以及所要加减的天数算出加减后的最终日期  addDay(String dateStr, int day) 或者(Date dateStr, int day)
 * 6.获取两个日期之间的天数(字符串日期)  getDiffDays(String startDay, String endDay) 或者 (Date startDay, Date endDay)
 * 8.通过传入日期以及特定样式转换为特定样式的日期 formatDate(Date date, String pattern)
 * 6.Date转化为String formatDate()
 * 7.String转化为Date parseDate()
 * 10.String转换为java.util.Date日期 strToDate(String dateStr)
 * 19.将任何格式的字符串转换为date  changeDate(sendTimeStr) sendTimeStr: Tue Jun 12 11:00:00 CST 2018  String类型
 * 11.时间字符串转换成Timestamp日期  strToTimestamp(String dateStr)
 * 12.验证字符串日期是否符合给定规则  checkDateStr(String dateStr, String reg)
 * 13.通过传入指定年及月份获得所在月份的天数 getMonthDays(int year, int month)
 * 14.获得当前系统时间所在月的最大天数   getCurMonthDays()
 * 15.通过传入指定年获得所在年的总天数  getYearDays(int year)
 * 16.获得当前日期是星期几  getWeekday(String dateStr) 或 (Date date)
 * 18.比较时间大小（日期格式-字符串类型）compareDate(String d1, String d2)  (date,date)
 * 	  0表示两个字符串日期相等；-1表示日期d1小于日期d2; 1表示日期d1大于日期d2;2表示输入参数为空.
 * 1.得到当前时间 getCurrentDate()
 * 2.得到当前年份字符串 getCurrentYear()
 * 3.得到当前月份字符串 getCurrentMonth()
 * 4.得到当天字符串 getCurrentDay()
 * 9.得到给定时间的给定天数后的日期 getAppointDate()
 * 11.获取过去的天数 pastDays()
 * 12.获取过去的小时 pastHour()
 * 13.获取过去的分钟  pastMinutes()
 * 14.得到本周的第一天  getFirstDayOfWeek()
 * 15.获取指定某年某月份的第一天 getFirstDayOfMonth(String yearMonth)  yearMonth yyyy-MM格式  2018-12
 *      String firstDayOfMonth = DateUtils.getFirstDayOfMonth("2020-04");
 * 16.获取指定某年某月份的最后一天 getLastDayOfMonth(String yearMonth) yearMonth：2018-12
 *      String lastDayOfMonth = DateUtils.getLastDayOfMonth("2020-04");
 * 17.得到下月的第一天 getFirstDayOfNextMonth()
 * 18.根据生日获取年龄 getAgeByBirthDate()
 * 19.判断字符串格式是否是 yyyy-mm-dd    formatDate(String dateStr)   d = sdf.parse(formatDate(map.get("backTime").toString()));
 * 20.date类型转时间戳类型 dataToTimestamp(Date date)
 * 21.时间戳转string类型日期 TimestampToData(long timeStamp)
 */

/**
 * 通过封装java API的日期函数处理的类库，本类中包含多数用户经常使用的获取各种日期格式转换的方法
 * @author 王磊
 */
public class DateUtils {

    /**
     * 日志
     */
    private final Log log = LogFactory.getLog(getClass());

    /**
     * 按指定样式获得系统时间,样式参数如yyyy-MM-dd,yyyy-MM-dd HH:mm:ss等
     *
     * @param pattern
     *            要获取时间的样式，如获取yyyy-MM-dd，则pattern="yyyy-MM-dd"，获取yyyy-MM-dd
     *            HH:mm:ss，则pattern="yyyy-MM-dd HH:mm:ss"
     * @return dateStr 日期字符串
     */
    public static String formatCurTime(String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String dateStr = sdf.format(new Date());
        return dateStr;
    }

    /**
     * 根据时区和指定样式获取该时区下的系统时间.
     *
     * @param timeZone
     *            时区字符串 如America/Los_Angeles,Asia/Shanghai;
     * @param pattern
     *            样式字符串 如yyyy-MM-dd,yyyy-MM-dd HH:mm:ss等
     * @return dateStr 系统日期字符串
     */
    public static String formatCurTime(String timeZone, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        TimeZone tz = TimeZone.getTimeZone(timeZone);
        sdf.setTimeZone(tz);
        String dateStr = sdf.format(new Date());
        return dateStr;
    }

    /**
     * 根据语言环境获得系统日期
     *
     * @param
     *            Locale
     * @return dateStr 系统日期字符串
     */
    public static String getCurTime(Locale locale) {
        DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
        String dateStr = df.format(new Date());
        return dateStr;
    }

    /**
     * 根据给定的字符串日期以及所要加减的天数算出加减后的最终日期
     *
     * @param dateStr
     *            指定字符串日期 格式为yyyy-MM-dd
     * @param day
     *            加减天数
     * @return dateNewStr 计算后的字符串日期
     */
    public static String addDay(String dateStr, int day) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        long myTime = (strToDate(dateStr).getTime() / 1000) + day * 24L * 60
                * 60;
        return sdf.format(myTime * 1000);
    }

    /**
     * 根据给定的日期以及所要加减的天数算出加减后的最终日期
     *
     * @param dateStr
     *            指定字符串日期 格式为yyyy-MM-dd
     * @param day
     *            加减天数
     * @return dateNewStr 计算后的字符串日期
     */
    public static String addDay(Date dateStr, int day) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        long myTime = (dateStr.getTime() / 1000) + day * 24L * 60 * 60;
        return sdf.format(myTime * 1000);
    }

    /**
     * 获得两个字符串日期的间隔天数
     *
     * @param startday
     *            字符串开始日期 格式为yyyy-MM-dd
     * @param endday
     *            字符串结束日期 格式为yyyy-MM-dd
     * @return int 间隔天数
     */
    public static int getDiffDays(String startDay, String endDay)
            throws Exception {
        Date sDay = strToDate(startDay);
        Date eDay = strToDate(endDay);
        return Integer.parseInt(String
                .valueOf((eDay.getTime() - sDay.getTime())
                        / (24 * 60 * 60 * 1000)));
    }

    /**
     * 获得两个日期的间隔天数
     *
     * @param startday
     *            字符串开始日期 格式为yyyy-MM-dd
     * @param endday
     *            字符串结束日期 格式为yyyy-MM-dd
     * @return int 间隔天数
     */
    public static int getDiffDays(Date startDay, Date endDay) {
        return Integer.parseInt(String.valueOf((endDay.getTime() - startDay
                .getTime())
                / (24 * 60 * 60 * 1000)));
    }

    /**
     * 通过传入日期以及特定样式转换为特定样式的日期。
     *
     * @param java
     *            .util.Date 日期
     * @param pattern
     *            日期格式化样式 如：（yyyy-MM-dd、yyyy/MM/dd）
     * @return String 格式化的字符串日期
     */
    public static String formatDate(Date date, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String dateString = sdf.format(date);
        return dateString;
    }

    /**
     * Date转化为String(yyyy-MM-dd HH:mm:ss)
     * @param date
     * @return
     */
    public static String formatDate(Date date){
        return formatDate(date,"yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 日期字符串转换为java.util.Date日期
     *
     * @param dateStr
     *            日期字符串
     * @return date 日期
     */
    public static Date strToDate(String dateStr) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        Date date = null;
        try {
            date = sdf.parse(dateStr, pos);
        } catch (Exception e) {
            throw new Exception("输入的字符串日期格式不正确，请检查");
        }
        return date;
    }

    /**
     * 时间字符串转换成Timestamp日期
     *
     * @param dateStr
     *            日期字符串
     * @return timestamp 日期
     */
    public static Date strToTimestamp(String dateStr) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new Exception("输入的字符串日期格式不正确，请检查");
        }
        return date == null ? null : new Timestamp(date.getTime());
    }

    /**
     * 验证字符串日期是否符合给定规则
     *
     * @param dateStr
     *            日期字符串
     * @param reg
     *            字符串样式
     * @return 是否合法 是true/否false
     */
    public static boolean checkDateStr(String dateStr, String reg)
            throws Exception {
        if (dateStr == null || "".equals(dateStr.trim())) {
            return false;
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat(reg);
            try {
                sdf.parse(dateStr);
                return true;
            } catch (ParseException pe) {
                return false;
            }
        }
    }

    /**
     * 通过传入指定年及月份获得所在月份的天数
     *
     * @param year
     *            年
     * @param month
     *            月
     * @return int 天数
     */
    public static int getMonthDays(int year, int month) {
        int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        if (2 == month && 0 == (year % 4)
                && (0 != (year % 100) || 0 == (year % 400))) {
            days[1] = 29;
        }
        return (days[month - 1]);
    }

    /**
     * 获得当前系统时间所在月的最大天数
     *
     * @return int 系统月最大天数
     */
    public static int getCurMonthDays() {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH) + 1;
        return getMonthDays(year, month);
    }

    /**
     * 通过传入指定年获得所在年的总天数
     *
     * @param year
     *            年
     * @return int 天数
     */
    public static int getYearDays(int year) throws Exception {
        String sDate = year + "-01-01";
        String eDate = year + "-12-31";
        return getDiffDays(sDate, eDate);
    }

    /**
     * 通过传入指定字符串日期获得该日期为星期几
     *
     * @param dateStr
     *            字符串日期 格式为yyyy-MM-dd,如2012-07-01
     * @return str 星期几字符串
     */
    public static String getWeekday(String dateStr) throws Exception {
        Date date = strToDate(dateStr);
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return new SimpleDateFormat("EEEE").format(c.getTime());
    }

    /**
     * 通过传入指定日期获得该日期为星期几
     *
     * @param dateStr
     *            字符串日期 格式为yyyy-MM-dd,如2012-07-01
     * @return str 星期几字符串
     */
    public static String getWeekday(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return new SimpleDateFormat("EEEE").format(c.getTime());
    }

    /**
     * 判断两个字符串日期的大小关系。0表示两个字符串日期相等；-1表示日期d1小于日期d2; 1表示日期d1大于日期d2;
     * 2表示输入参数为空.字符串日期参数格式为yyyy-MM-dd
     *
     * @param d1
     *            字符串日期
     * @param d2
     *            字符串日期
     * @param pattern
     *            日期格式 yyyy-MM-dd
     * @return 整型数据 int
     */
    public static int compareDate(String d1, String d2, String pattern) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        if (d1 != null && !d1.equals("") && d2 != null && !d2.equals("")) {
            Date dt1 = null;
            Date dt2 = null;
            try {
                dt1 = sdf.parse(d1);
                dt2 = sdf.parse(d2);
            } catch (Exception e) {
                throw new Exception("输入的字符串日期格式不正确，请检查");
            }
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        }
        return 2;
    }

    /**
     * 判断两个日期的大小关系。0表示两个日期相等；-1表示日期d1小于日期d2; 1表示日期d1大于日期d2; 2表示输入参数为空.
     *
     * @param d1
     *            日期
     * @param d2
     *            日期
     * @return 整型数据 int
     */
    public static int compareDate(Date d1, Date d2) {
        if (d1 != null && d2 != null) {
            if (d1.getTime() > d2.getTime()) {
                return 1;
            } else if (d1.getTime() < d2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        }
        return 2;
    }

    /**
     * 得到当前时间(yyyy-MM-dd HH:mm:ss)
     * @return
     */
    public static String getCurrentDate(){
        return formatDate(new Date());
    }

    /**
     * 得到当前时间
     * @param formate 格式
     * @return
     */
    public static String getCurrentDate(String formate){
        return formatDate(new Date(),formate);
    }

    /**
     * 得到当前年份字符串
     */
    public static String getCurrentYear() {
        return formatDate(new Date(), "yyyy");
    }

    /**
     * 得到当前月份字符串
     */
    public static String getCurrentMonth() {
        return formatDate(new Date(), "MM");
    }

    /**
     * 得到当天字符串
     */
    public static String getCurrentDay() {
        return formatDate(new Date(), "dd");
    }

    /**
     * String转化为Date
     * @param date
     * @param formate
     * @return
     */
    public static Date parseDate(String date, String formate){
        SimpleDateFormat sdf = new SimpleDateFormat(formate);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * String转化为Date
     * @param date
     * @return
     */
    public static Date parseDate(String date){
        return parseDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 得到给定时间的给定天数后的日期
     * @return
     */
    public static Date getAppointDate(Date date, int day){
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, day);
        return calendar.getTime();
    }


    /**
     * 获取过去的天数
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取过去的小时
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 60 * 1000);
    }

    /**
     * 获取过去的分钟
     * @param date
     * @return
     */
    public static long pastMinutes(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 得到本周的第一天
     * @return
     */
    public static Date getFirstDayOfWeek(){
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTime();
    }

    /**
     * 得到下月的第一天
     * @return
     */
    public static Date getFirstDayOfNextMonth() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, +1);
        int firstDay = cal.getMinimum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        return cal.getTime();
    }

    /**
     * 根据生日获取年龄
     * @param birtnDay
     * @return
     */
    public static int getAgeByBirthDate(Date birtnDay) {
        Calendar cal = Calendar.getInstance();
        if (cal.before(birtnDay)) {
            return 0;
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birtnDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        int age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    /**
     * 将任何格式的字符串转换为date
     */
    private Date changeDate(String otherDate) {
        Date date = null;
        SimpleDateFormat simpleDateFormat = null;
        try {
            simpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
            date = simpleDateFormat.parse(otherDate);
        } catch (Exception e) {
            log.error(e);
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                date = simpleDateFormat.parse(otherDate);
            } catch (ParseException e1) {
                log.error(e1);
                throw new IllegalArgumentException("parse date failed, " + date);
            }
        }
        return date;
    }

    /**
     * 获取指定某年某月的第一天  getFirstDayOfMonth(String yearMonth)  yearMonth yyyy-MM格式  2018-12
     *  Calendar cal = Calendar.getInstance();  当前时间
     * @return
     */
    public static String getFirstDayOfMonth(String yearMonth) {
        int year = Integer.parseInt(yearMonth.split("-")[0]);  //年
        int month = Integer.parseInt(yearMonth.split("-")[1]); //月
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置月份
        cal.set(Calendar.MONTH, month - 1);
        int firstDay = cal.getMinimum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * @Description: 获取指定某年某月份的最后一天
     * @Date 2019/6/3 10:52
     * @param: yearMonth yyyy-MM格式  2018-12
     * @return: java.lang.String
     */
    public static String getLastDayOfMonth(String yearMonth) {
        int year = Integer.parseInt(yearMonth.split("-")[0]);  //年
        int month = Integer.parseInt(yearMonth.split("-")[1]); //月
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置月份
        cal.set(Calendar.MONTH, month - 1);
        // 获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        // 设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    /**
     * function :判断字符串格式是否是 yyyy-mm-dd,及Excel改变的格式：EEE MMM dd HH:mm:ss zzz yyyy
     * @author Administrator
     * @param dateStr
     * @return 返回一个yyyy-mm-dd格式的字符串或者空字符串
     */
    private String formatDate(String dateStr) {
        String result = "";
        Date date = null;
        SimpleDateFormat yyyyMMddFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        boolean isYyyyMMdd;
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
            date = simpleDateFormat.parse(dateStr);
            isYyyyMMdd = true;
        } catch (Exception e) {
            isYyyyMMdd = false;
            log.error(e);
        }

        if (isYyyyMMdd) {
            result = yyyyMMddFormat.format(date);
        } else {
            try {
                date = yyyyMMddFormat.parse(dateStr);
                isYyyyMMdd = true;
            } catch (Exception e1) {
                isYyyyMMdd = false;
                log.error(e1);
            }
            if (isYyyyMMdd) {
                result = dateStr;
            }
        }
        return result;
    }

    /**
     * date类型转时间戳类型
     */
    private Timestamp dataToTimestamp(Date date){
        Timestamp timestamp = new Timestamp(date.getTime());
        return timestamp;//2020-05-12 11:50:41.961
    }

    /**
     * 时间戳转string类型日期
     */
    private String TimestampToData(long timeStamp){
        //long timeStamp = 1495777335060;//直接是时间戳
//        long timeStamp = System.currentTimeMillis();  //获取当前时间戳,也可以是你自已给的一个随机的或是别人给你的时间戳(一定是long型的数据)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//这个是你要转成后的时间的格式
        String sd = sdf.format(new Date(timeStamp));   // 时间戳转换成时间
//        System.out.println(sd);//打印出你要的时间   结果就是: 2017-05-26 13:42:15
        return sd;
    }
}

